﻿/* ######################################## *\
 * ### Copyright (C) 2009 AJ Ravindiran ### *
\* ######################################## */
using System;
using System.Threading;

using AJRavindiran.Jolt.Storage;
using AJRavindiran.Jolt.Network.Tcp;
using AJRavindiran.Jolt.Utilities.Debug;
using AJRavindiran.Jolt.Utilities.Parsing;

namespace AJRavindiran.Jolt
{
    /// <summary>
    /// Represents the environment, portal to everything within.
    /// </summary>
    public static class Jolt
    {
        #region Fields
        private static Log log = new Log();

        private static DatabaseManager databaseManager;
        private static TcpConnection tcpConnection;
        private static RuneScape.RuneScape runescape;

        private static Thread monitorThread = new Thread(new ThreadStart(Monitor));
        #endregion Fields

        #region Properties
        /// <summary>
        /// Gets the DebugMode status.
        /// </summary>
        public static bool DebugMode
        {
            get { return Program.DebugMode; }
        }

        /// <summary>
        /// Gets the WriteEnabled status.
        /// </summary>
        public static bool WriteEnabled
        {
            get { return Program.WriteEnabled; }
        }
        #endregion Properties

        #region Methods
        /// <summary>
        /// Sets up the database and tcp connections, and sets up runescape emulator.
        /// </summary>
        public static void Initialize()
        {
            log.WriteInfo("Welcome to Jolt Environment - Initializing...");

            if (DebugMode)
            {
                log.LogPriority = LogLevel.Debug;
                log.WriteWarn("You are in debug mode, all errors will show.");
            }
            else
            {
                log.LogPriority = LogLevel.Info;
            }

            try
            {
                Xml xml = new Xml("system_general.xml");

                #region Database Initialization
                DatabaseServer databaseServer = new DatabaseServer(
                    xml.ReadString("database.host"),
                    xml.ReadUInt32("database.port"),
                    xml.ReadString("database.user"),
                    xml.ReadString("database.pass"));

                Database database = new Database(
                    xml.ReadString("database.name"),
                    xml.ReadUInt32("database.minpoolsize"),
                    xml.ReadUInt32("database.maxpoolsize"));

                databaseManager = new DatabaseManager(databaseServer, database);
                databaseManager.SetClientAmount(2);
                databaseManager.ReleaseClient(databaseManager.GetClient().Handle);
                databaseManager.StartMonitor();
                #endregion Database Initialization

                #region TCP Initialization
                tcpConnection = new TcpConnection(
                    xml.ReadInt32("tcp.port"),
                    xml.ReadInt32("tcp.maxcon"));
                #endregion TCP Initialization

                xml = null;

                // Start the monitor thread @ lowest priority.
                monitorThread.Priority = ThreadPriority.Lowest;
                monitorThread.Start();

                // If this message has been reached, the environment has been set up 
                // correctly, and is now moving on to setting up the gaming environment.
                log.WriteInfo("Successfully set up Jolt Environment.");
                log.WriteBlank();

                //Start the runescape emulation.
                RuneScape.RuneScape.Initialize();
            }
            catch (Exception ex)
            {
                log.WriteException(ex);
                log.WriteError("Jolt Environment has failed to start up.");
                log.WriteInfo("Press any key to complete shutdown..");
                Console.ReadKey(false);
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// Shuts down the database and tcp connections, and
        /// closes the runescape emulator.
        /// </summary>
        public static void ShutDown()
        {
            log.WriteInfo("Jolt Environment is now shutting now...");

            if (monitorThread.IsAlive)
                monitorThread.Abort();
            Console.Title = "Jolt Environment [SHUTDOWN]";

            if (databaseManager != null)
            {
                log.WriteInfo("Shutting down database(s)...");
                databaseManager.StopMonitor();
                databaseManager.DestroyClients();
                databaseManager.DestroyManager();
            }

            log.WriteInfo("Shutdown complete. Press any key to continue...");
            Console.ReadKey();
            Environment.Exit(0);
        }

        /// <summary>
        /// A threaded monitor which updates the title with 
        /// the current ammount of garbage collection memory.
        /// </summary>
        private static void Monitor()
        {
            DateTime startTime = DateTime.Now;
            while (true)
            {
                Console.Title = "Jolt Environment [Garbage Collection: " + GC.GetTotalMemory(false) / 1024 + "KB | Uptime: " + (DateTime.Now - startTime) + "]";
                try
                {
                    Thread.Sleep(1000);
                }
                catch
                {
                    Jolt.GetLog().WriteWarn("Monitor failed to update.");
                }
            }
        }

        /// <summary>
        /// Accessor for the log class.
        /// </summary>
        public static Log GetLog()
        {
            return log;
        }

        /// <summary>
        /// Accessor for the runescape class.
        /// </summary>
        /// <returns></returns>
        public static RuneScape.RuneScape GetRuneScape()
        {
            return runescape;
        }

        /// <summary>
        /// Accessor for the database class(es).
        /// </summary>
        public static DatabaseManager GetDatabase()
        {
            return databaseManager;
        }

        /// <summary>
        /// Accessor for the tcp connection.
        /// </summary>
        public static TcpConnection GetTcpConnection()
        {
            return tcpConnection;
        }
        #endregion Methods
    }
}
